﻿using System.Threading.Tasks;
using EventHub.Organizations.Plans;
using Volo.Abp;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Domain.Services;
using Volo.Abp.Guids;
using Volo.Abp.Identity;
using Volo.Abp.Timing;

namespace EventHub.Events.Registrations
{
    /// <summary>
    /// 领域服务
    /// 不需要单独为领域服务声明接口
    /// 领域服务是领域不可分割的一部分，不需要单独声明接口
    /// 领域服务不对实体进行修改，只负责
    /// </summary>
    public class EventRegistrationManager : DomainService
    {
        private readonly IEventRegistrationRepository _eventRegistrationRepository;
        private readonly IGuidGenerator _guidGenerator; // ABP框架提供的，生成有序GUID的服务
        private readonly IClock _clock;// IClock接口提供“本地化”时间（本地时区的时间）
        private readonly PlanFeatureManager _planFeatureManager;

        public EventRegistrationManager(
            IEventRegistrationRepository eventRegistrationRepository,// 领域服务中可以依赖注入仓储
            IGuidGenerator guidGenerator, // 注入ABP框架的 IGuidGenerator 服务
            IClock clock, // 注入ABP框架的 IClock服务，获取本地化时间
            PlanFeatureManager planFeatureManager)
        {
            _eventRegistrationRepository = eventRegistrationRepository;
            _guidGenerator = guidGenerator;
            _clock = clock;
            _planFeatureManager = planFeatureManager;
        }

        // 领域服务方法不应该更新实体，这是一个"基本的原则"


        /// <summary>
        /// 注册活动
        /// 领域业务逻辑
        /// 领域业务逻辑等级低于应用业务逻辑，领域业务逻辑是业务逻辑的最小组成部分，在业务逻辑概念中拥有"原子性"
        /// </summary>
        public async Task RegisterAsync(
            Event @event,
            IdentityUser user)
        {
            if (IsPastEvent(@event))
            {
                throw new BusinessException(EventHubErrorCodes.CantRegisterOrUnregisterForAPastEvent);
            }

            if (await IsRegisteredAsync(@event, user))
            {
                return;
            }
            
            if (@event.Capacity != null)
            {
                var registrationCount = await _eventRegistrationRepository.CountAsync(x => x.EventId == @event.Id);
                if (registrationCount >= @event.Capacity)
                {
                    throw new BusinessException(EventHubErrorCodes.CapacityOfEventFull)
                        .WithData("EventTitle", @event.Title);
                }
            }

            if (!await _planFeatureManager.CanRegisterToEventAsync(@event))
            {
                throw new BusinessException(EventHubErrorCodes.CannotRegisterToEvent);
            }
                
            await _eventRegistrationRepository.InsertAsync(

                // 创建聚合实体的操作一般放在“领域服务中”
                new EventRegistration(
                    _guidGenerator.Create(),
                    @event.Id,
                    user.Id
                )
            );
        }

        /// <summary>
        /// 取消活动注册
        /// 领域业务逻辑
        /// 领域业务逻辑是业务逻辑中最小组成部分，用来给"应用层业务逻辑调用的"
        /// </summary>
        /// <param name="event"></param>
        /// <param name="user"></param>
        /// <returns></returns>
        /// <exception cref="BusinessException"></exception>
        public async Task UnregisterAsync(
            Event @event,
            IdentityUser user)
        {
            if (IsPastEvent(@event))
            {
                throw new BusinessException(EventHubErrorCodes.CantRegisterOrUnregisterForAPastEvent);
            }

            await _eventRegistrationRepository.DeleteAsync(
                x => x.EventId == @event.Id && x.UserId == user.Id
            );
        }

        /// <summary>
        /// 判断用户是否注册了某活动
        /// </summary>
        public async Task<bool> IsRegisteredAsync(
            Event @event,
            IdentityUser user)
        {
            return await _eventRegistrationRepository
                .ExistsAsync(@event.Id, user.Id);
        }

        /// <summary>
        /// 是否错过活动
        /// </summary>
        /// <param name="event"></param>
        /// <returns></returns>
        public bool IsPastEvent(Event @event)
        {
            return _clock.Now > @event.EndTime;
        }
    }
}
